package imachine;

import java.util.ArrayList;

/**
 * Class for Finite State Machines. A FSM is comprised of a group of states, a
 * group of transitions, a group events, and a group of transitions. <br>
 * <br>
 * FSM could serve as a generic framework or pattern in software development,
 * and is very suitable for representing event driven models. <br>
 * <br>
 * The IMachine project is purposed to provide a generic, powerful yet
 * easy-to-use framework for state machine related software development. The
 * framework consists of following components: <br>
 * 1. The Naked State Machine which represents an abstract state machine model;
 * <br>
 * 2. The Machine Engine which can drive a state machine; <br>
 * 3. The Action Registration Mechanism which allows user actions to be hooked
 * onto a state machine dynamically when it runs. <br>
 * <br>
 * This class is an abstract class for state machine designers to customize
 * specific Finite State Machines.
 * 
 * @version 0.0.1
 * @author Xiong Yi: xiongyee2000@gmail.com
 */
public abstract class Machine {
	/**
	 * The array to store all states. Add all states to this array when
	 * subclassing.
	 */
	protected ArrayList<State> states = new ArrayList<State>();

	/**
	 * The array to store all transitions. Add all transitions to this array
	 * when subclassing.
	 */
	protected ArrayList<Transition> transitions = new ArrayList<Transition>();

	/**
	 * The array to store all triggers. Add all triggers to this array when
	 * subclassing.
	 */
	protected ArrayList<Trigger> triggers = new ArrayList<Trigger>();

	/**
	 * Constructor. Used only by the subclass.
	 * 
	 */
	protected Machine() {
	}

	/**
	 * Get the id of the entry state of the state machine. Note a FSM must have
	 * a unique entry state.
	 * 
	 * @return The id of the entry state.
	 */
	public abstract int getEntryStateId();

	/**
	 * Get the id of the state machine.
	 * 
	 * @return The id of the state machine.
	 */
	public abstract int getId();

	/**
	 * Get the name of the state machine.
	 * 
	 * @return The name of the state machine.
	 */
	public abstract String getName();

	/**
	 * Get the state by id. Note the id is the index stored in the state array
	 * in this machine.
	 * 
	 * @param id
	 *            the id of the state
	 * @return The state instance.
	 */
	public State getState(int id) {
		State rtn = null;
		if (id >= 0 && id < states.size()) {
			rtn = states.get(id);
		}
		return rtn;
	}

	/**
	 * Get the number of states the state machine has.
	 * 
	 * @return the number of states.
	 */
	public int getStateNum() {
		return states.size();
	}

	/**
	 * Get the transition by id. Note the id is the index stored in the
	 * transition array in this machine.
	 * 
	 * @param id
	 *            the id of the transition
	 * @return The transition instance.
	 */
	public Transition getTransition(int id) {
		Transition rtn = null;
		if (id >= 0 && id < transitions.size()) {
			rtn = transitions.get(id);
		}
		return rtn;
	}

	/**
	 * Get the number of transitions the state machine has.
	 * 
	 * @return The number of transitions.
	 */
	public int getTransitionNum() {
		return transitions.size();
	}

	/**
	 * Get the trigger by id. Note the id is the index stored in the trigger
	 * array in this machine.
	 * 
	 * @param id
	 *            the id of the trigger
	 * @return The trigger instance.
	 */
	public Trigger getTrigger(int id) {
		Trigger rtn = null;
		if (id >= 0 && id < triggers.size()) {
			rtn = triggers.get(id);
		}
		return rtn;
	}

	/**
	 * Get the number of triggers the state machine has.
	 * 
	 * @return The number of triggers.
	 */
	public int getTriggerNum() {
		return triggers.size();
	}
}
